home *** CD-ROM | disk | FTP | other *** search
- #!/usr/local/bin/tclsh
- #
- # weed out certain undesirables from an eggdrop userlist
- # try just typing 'tclsh weed' to find out the options
- # Robey Pointer, november 1994
- #
- # <cmwagner@gate.net>:
- # I did a few bug fixes to the original weed script, things changed...
- #
- # when specifying other weed options they would unset the User() field and
- # a maxlast weed would try and weed again and cause the script to stop due
- # to User() being already unset (array nonexistant)
- #
- # when loadUserFile encountered an xtra field it would try and use the $info
- # variable, which was supposed to be $xtra (something overlooked when the
- # line was cut and pasted -- I hate it when that happens)
- #
- # changed the formatting of the saved weed file to match more closely to
- # eggdrop 0.9tp (so this may cause incompatibilities), but when a hostmask
- # field exactly matched 40 characters it would save it with no spaces after it
- # and eggdrop would reject the user record. I know I could have easily changed
- # one character, but I couldn't help myself. <grin>
- # 5 march 96
- #
- # <robey, 23jul96>:
- # upgrade for v2 userfiles
- #
- # <bruce s, 4sep96>:
- # fixed xtra field from getting truncated
- #
- # <robey, 20sep96>:
- # stopped it from mangling channel ban lists
-
-
- # by default, banlist and ignorelist are exempt from weeding
- set exempt {*ban *ignore}
-
- # don't exempt ops, masters, or friends; or +p or +x
- set exemptops 0 ; set exemptmasters 0 ; set exemptfriends 0
- set exemptparty 0 ; set exemptfile 0
-
- # default maximum seconds since last seen: 0 = infinite
- set maxlast 0
-
- # default maximum seconds since ban used: 0 = infinite
- set maxban 0
- # default maximum seconds since ignore created: 0 = infinite
- set maxignore 0
-
- # don't weed passwordless ops and/or masters -- don't weed ppl w/ no pw
- set weedops 0 ; set weedmasters 0 ; set weednopw 0
-
- # don't unop/unmaster passwordless ops and/or masters
- set stripops 0 ; set stripmasters 0
-
- # don't weed people just cos they've never logged on
- set weedlurkers 0
-
-
- # tricky way to get the current timestamp
- set fd [open "/tmp/egg.timer." w]
- close $fd
- set CURRENT [file atime "/tmp/egg.timer."]
- exec rm -f /tmp/egg.timer.
-
- if {$argc < 1} {
- puts stdout "\nUsage: weed <userfile> \[options\]"
- puts stdout " (weeds out users from an eggdrop userlist)"
- puts stdout "Output goes to <userfile>.weed"
- puts stdout "Possible options:"
- puts stdout " -<nick> exempt this user from weeding"
- puts stdout " ^o ^m ^f exempt ops or masters or friends"
- puts stdout " ^p ^x exempt party-line or file-area users"
- puts stdout " +<days> weed: haven't been seen in N days"
- puts stdout " :n weed: haven't EVER been seen"
- puts stdout " :o :m weed: ops or masters with no password set"
- puts stdout " :a weed: anyone with no pasword set"
- puts stdout " o m unop/unmaster: ops or masters with no pass."
- puts stdout " b<days> weed: bans not used in N days"
- puts stdout " i<days> weed: ignores created over N days ago"
- puts stdout ""
- exit
- }
- puts stdout "\nWEED 5mar96, robey\n"
-
- # process arguments
- set filename [lindex $argv 0]
- for {set i 1} {$i < $argc} {incr i} {
- # each arg
- set carg [lindex $argv $i]
- if {$carg == ":n"} {
- set weedlurkers 1
- } elseif {$carg == ":o"} {
- set weedops 1 ; set stripops 0 ; set weednopw 0
- } elseif {$carg == ":m"} {
- set weedmasters 1 ; set stripmasters 0 ; set weednopw 0
- } elseif {$carg == ":a"} {
- set weednopw 1 ; set weedops 0 ; set weedmasters 0
- set stripops 0 ; set stripmasters 0
- } elseif {$carg == "o"} {
- set stripops 1 ; set weedops 0 ; set weednopw 0
- } elseif {$carg == "m"} {
- set stripmasters 1 ; set weedmasters 0 ; set weednopw 0
- } elseif {$carg == "^m"} {
- set exemptmasters 1
- } elseif {$carg == "^o"} {
- set exemptops 1
- } elseif {$carg == "^f"} {
- set exemptfriends 1
- } elseif {$carg == "^p"} {
- set exemptparty 1
- } elseif {$carg == "^x"} {
- set exemptfile 1
- } elseif {[string index $carg 0] == "-"} {
- lappend exempt [string range $carg 1 end]
- } elseif {[string index $carg 0] == "+"} {
- set maxlast [expr 60*60*24* [string range $carg 1 end]]
- } elseif {[string index $carg 0] == "b"} {
- set maxban [expr 60*60*24* [string range $carg 1 end]]
- } elseif {[string index $carg 0] == "i"} {
- set maxignore [expr 60*60*24* [string range $carg 1 end]]
- } else {
- puts stderr "UNKNOWN OPTION: '$carg'\n"
- exit
- }
- }
-
- if {(!$weedlurkers) && (!$weedops) && (!$weedmasters) && (!$weednopw) &&
- (!$stripops) && (!$stripmasters) && ($maxlast == 0) &&
- ($maxban == 0) && ($maxignore == 0)} {
- puts stderr "PROBLEM: You didn't specify anything to weed out.\n"
- exit
- }
- set weeding {}
- if {$weedlurkers} { set weeding "$weeding lurkers" }
- if {$weedops} { set weeding "$weeding pwdless-ops" }
- if {$weedmasters} { set weeding "$weeding pwdless-masters" }
- if {$weednopw} { set weeding "$weeding pwdless-users" }
- if {$maxlast > 0} {
- set weeding "$weeding >[expr $maxlast /(60*60*24)]-days"
- }
- if {$maxban > 0} {
- set weeding "$weeding bans>[expr $maxban /(60*60*24)]-days"
- }
- if {$maxignore > 0} {
- set weeding "$weeding ign>[expr $maxignore /(60*60*24)]-days"
- }
- if {$weeding != {}} { puts stdout "Weeding:$weeding" }
- set strip {}
- if {$stripops} { set strip "$strip pwdless-ops" }
- if {$stripmasters} { set strip "$strip pwdless-masters" }
- if {$strip != {}} { puts stdout "Stripping:$strip" }
- set exempting {}
- if {$exemptops} { set exempting "$exempting (ops)" }
- if {$exemptmasters} { set exempting "$exempting (masters)" }
- if {$exemptfriends} { set exempting "$exempting (friends)" }
- if {$exemptparty} { set exempting "$exempting (party-line)" }
- if {$exemptfile} { set exempting "$exempting (file-area)" }
- if {[llength $exempt]>2} { set exempting "$exempting [lrange $exempt 2 end]" }
- if {$exempting != {}} { puts stdout "Exempt:$exempting" }
-
- puts stdout "\nReading $filename ..."
-
- # User($handle) { "password" "attr" "timestamp" "dccdir" "email"
- # "comment" "infoline" "xtra" }
- # Hostmask($handle) { "*!*@*" "*!*@*" ... }
- #
- # -hostmask(s) *dccdir +email =comment :infoline
-
- # returns 1 if loaded okay
- proc loadUserFile {fname} {
- global User Hostmask
- set oldhandle {}
- if {[catch {set fd [open $fname r]}] != 0} { return 0 }
- set line [string trim [gets $fd]]
- if {[string range $line 1 2] != "2v"} {
- puts stderr "Unknown userfile version! (not v2)\n"
- exit
- }
- while {![eof $fd]} {
- set line [string trim [gets $fd]]
- if {([string index $line 0] != "#") && ([string length $line] > 0)} {
- # not a comment, and something on the line!
- scan $line "%s" handle
- if {$handle == "-"} {
- # hostmask list (shudder!)
- set hmList [split [string range $line 2 end] ,]
- # trim the items in this list (remove whitespace)
- for {set i 0} {$i < [llength $hmList]} {incr i} {
- lappend Hostmask($oldhandle) [string trim [lindex $hmList $i]]
- }
- } elseif {$handle == "*"} {
- # dccdir
- set dccdir [string trim [string range $line 2 end]]
- set User($oldhandle) [lreplace $User($oldhandle) 3 3 $dccdir]
- } elseif {$handle == "+"} {
- # email
- set email [string trim [string range $line 2 end]]
- set User($oldhandle) [lreplace $User($oldhandle) 4 4 $email]
- } elseif {$handle == "="} {
- # comment
- set comment [string trim [string range $line 2 end]]
- set User($oldhandle) [lreplace $User($oldhandle) 5 5 $comment]
- } elseif {$handle == ":"} {
- # user info line
- set info [string trim [string range $line 2 end]]
- set User($oldhandle) [lreplace $User($oldhandle) 6 6 $info]
- } elseif {$handle == "."} {
- # xtra field
- set xtra [lindex $User($oldhandle) 7]
- lappend xtra [string trim [string range $line 2 end]]
- set User($oldhandle) [lreplace $User($oldhandle) 7 7 $xtra]
- } else {
- # begin of new user
- scan $line "%s %s %s %s" handle pass attr ts
- set User($handle) [list $pass $attr $ts {} {} {} {} {}]
- set Hostmask($handle) {}
- set oldhandle $handle
- }
- }
- }
- return 1
- }
-
- # returns 1 if saved okay
- proc saveUserFile fname {
- global User Hostmask
- if {[catch {set fd [open $fname w]}] != 0} { return 0 }
- puts $fd "#2v: weed! now go away."
- foreach i [array names User] {
- set hmask "none"
- set loop 0
- set pass [lindex $User($i) 0]
- set attr [lindex $User($i) 1]
- set ts [lindex $User($i) 2]
- puts $fd [format "%-9s %-20s %-24s %s" $i $pass $attr $ts]
- for {} {$loop < [llength $Hostmask($i)]} {incr loop} {
- puts $fd "- [lindex $Hostmask($i) $loop]"
- }
- if {[lindex $User($i) 3] != {}} { puts $fd "* [lindex $User($i) 3]" }
- if {[lindex $User($i) 4] != {}} { puts $fd "+ [lindex $User($i) 4]" }
- if {[lindex $User($i) 5] != {}} { puts $fd "= [lindex $User($i) 5]" }
- if {[lindex $User($i) 6] != {}} { puts $fd ": [lindex $User($i) 6]" }
- if {[lindex $User($i) 7] != {}} {
- foreach xline [lindex $User($i) 7] {
- puts $fd ". $xline"
- }
- # puts $fd ". [lindex $User($i) 7]"
- }
- }
- close $fd
- return 1
- }
-
- if {![loadUserFile $filename]} {
- puts stderr "* Couldn't load userfile!\n"
- exit
- }
- puts stdout "Loaded. Weeding..."
- puts stdout "(pwd = no pass, -o/-m = removed op/master, lrk = never seen, exp = expired)\n"
-
- #
- # the main part
- #
- set total 0
- set weeded 0
- foreach i [array names User] {
- incr total
- set attr [lindex $User($i) 1]
- if {([lsearch -exact $exempt $i] == -1) &&
- ([string range $i 0 1] != "::") &&
- (([string first o $attr] == -1) || (!$exemptops)) &&
- (([string first m $attr] == -1) || (!$exemptmasters)) &&
- (([string first f $attr] == -1) || (!$exemptfriends)) &&
- (([string first p $attr] == -1) || (!$exemptparty)) &&
- (([string first x $attr] == -1) || (!$exemptfile))} {
- # not exempt from weeding
- set pass [lindex $User($i) 0]
- set ts [lindex $User($i) 2]
- if {([string compare $pass "-"] == 0) &&
- ([string first b $attr] == -1)} {
- # no password, bad boy/girl!
- if {$weednopw == 1} {
- unset User($i) ; incr weeded
- puts -nonewline stdout "[format "pwd: %-10s " $i]"
- } elseif {([string first o $attr] != -1) && ($weedops == 1)} {
- unset User($i) ; incr weeded
- puts -nonewline stdout "[format "pwd: %-10s " $i]"
- } elseif {([string first m $attr] != -1) && ($weedmasters == 1)} {
- unset User($i) ; incr weeded
- puts -nonewline stdout "[format "pwd: %-10s " $i]"
- }
- if {([string first o $attr] != -1) && ($stripops == 1)} {
- set nattr {}
- for {set x 0} {$x < [string length $attr]} {incr x} {
- if {[string index $attr $x] != "o"} {
- set nattr [format "%s%s" $nattr [string index $attr $x]]
- }
- }
- if {$nattr == {}} { set nattr "-" }
- set User($i) [lreplace $User($i) 1 1 $nattr]
- puts -nonewline stdout "[format " -o: %-10s " $i]"
- }
- if {([string first m $attr] != -1) && ($stripmasters == 1)} {
- set nattr {}
- for {set x 0} {$x < [string length $attr]} {incr x} {
- if {[string index $attr $x] != "m"} {
- set nattr [format "%s%s" $nattr [string index $attr $x]]
- }
- }
- if {$nattr == {}} { set nattr "-" }
- set User($i) [lreplace $User($i) 1 1 $nattr]
- puts -nonewline stdout "[format " -m: %-10s " $i]"
- }
- }
- if {($ts == 0) && ($weedlurkers==1) && ([string first b $attr]==-1) &&
- [info exists User($i)]} {
- unset User($i) ; incr weeded
- puts -nonewline stdout "[format "lrk: %-10s " $i]"
- }
- if {($ts > 0) && ($maxlast > 0) && ($CURRENT-$ts > $maxlast &&
- [info exists User($i)])} {
- unset User($i) ; incr weeded
- puts -nonewline stdout "[format "exp: %-10s " $i]"
- }
- }
- flush stdout
- }
- puts stdout "\n"
-
- # now check bans/ignores
- foreach i [array names User] {
- if {([string range $i 0 1] == "::") || ($i == "*ban")} {
- # channel-specific bans!
- for {set j 0} {$j < [llength $Hostmask($i)]} {incr j} {
- set ban [split [lindex $Hostmask($i) $j] :]
- # make sure it's a modern ban:
- if {[string range [lindex $ban 2] 0 0] == "+"} {
- set lastused [lindex $ban 3]
- if {($maxban > 0) && ($CURRENT-$lastused > $maxban)} {
- if {$i == "*ban"} {
- puts stdout "Expired ban: [lindex $ban 0]"
- } {
- puts stdout "Expired ban on [string range $i 2 end]: [lindex $ban 0]"
- }
- set Hostmask($i) [lreplace $Hostmask($i) $j $j]
- incr j -1
- }
- }
- }
- }
- if {$i == "*ignore"} {
- for {set j 0} {$j < [llength $Hostmask($i)]} {incr j} {
- set ign [split [lindex $Hostmask($i) $j] :]
- set lastused [lindex $ign 3]
- if {($maxignore > 0) && ($CURRENT-$lastused > $maxignore)} {
- puts stdout "Expired ignore: [lindex $ign 0]"
- set Hostmask($i) [lreplace $Hostmask($i) $j $j]
- incr j -1
- }
- }
- }
- }
-
- puts stdout "\nFinished scan."
- puts stdout "Original total ($total), new total ([expr $total-$weeded]), zapped ($weeded)"
-
- if {![saveUserFile $filename.weed]} {
- puts stderr "* Couldn't save new userfile!\n"
- exit
- }
- puts stdout "Wrote $filename.weed"
-